package com.resume.aipeople.service;

import com.resume.aipeople.dto.ChatRequest;
import com.resume.aipeople.dto.ChatResponse;
import com.resume.aipeople.dto.ChatSessionDTO;
import com.resume.aipeople.dto.ChatMessageDTO;
import com.resume.aipeople.dto.CharacterDTO;
import com.resume.aipeople.entity.Character;
import com.resume.aipeople.entity.ChatMessage;
import com.resume.aipeople.entity.ChatSession;
import com.resume.aipeople.entity.User;
import com.resume.aipeople.repository.ChatMessageRepository;
import com.resume.aipeople.repository.ChatSessionRepository;
import com.resume.aipeople.service.ai.AISkillService;
import com.resume.aipeople.service.ai.LLMService;
import com.resume.aipeople.service.ai.VoiceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class ChatService {
    
    private final CharacterService characterService;
    private final LLMService llmService;
    private final AISkillService aiSkillService;
    private final VoiceService voiceService;
    private final ChatSessionRepository sessionRepository;
    private final ChatMessageRepository messageRepository;
    private final UserService userService;
    
    // 简单回复缓存，提高常见问题的响应速度
    private final ConcurrentHashMap<String, String> responseCache = new ConcurrentHashMap<>();
    
    public ChatResponse chat(ChatRequest request) {
        long startTime = System.currentTimeMillis();
        
        try {
            // 1. 强制要求登录
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication == null || !authentication.isAuthenticated() || "anonymousUser".equals(authentication.getName())) {
                return new ChatResponse("请先登录后再进行对话");
            }
            
            // 2. 获取角色信息（读操作，不需要事务）
            Optional<Character> characterOpt = characterService.findById(request.getCharacterId());
            if (!characterOpt.isPresent()) {
                return new ChatResponse("指定的角色不存在");
            }
            
            Character character = characterOpt.get();
            
            // 3. 获取或创建会话（短事务）
            ChatSession session = getOrCreateSessionTransactional(request, character);
            
            // 4. 保存用户消息（短事务）
            ChatMessage userMessage = saveUserMessageTransactional(session, request);
            
            // 5. 选择AI技能（无需事务）
            String selectedSkill = request.getPreferredSkill() != null ? 
                request.getPreferredSkill() : aiSkillService.selectBestSkill(request.getMessage());
            
            // 6. 检测情感（无需事务）
            String detectedEmotion = aiSkillService.detectEmotion(request.getMessage());
            
            // 7. 生成AI回复（异步处理，不阻塞）
            String aiResponse = generateAIResponseAsync(character, request.getMessage(), selectedSkill, session);
            
            // 8. 保存AI消息（短事务，不包含语音生成）
            ChatMessage aiMessage = saveAIResponseTransactional(session, aiResponse, selectedSkill, detectedEmotion, character.getId());
            
            // 9. 异步生成语音（不阻塞响应）
            generateAudioAsync(aiResponse, character.getName(), aiMessage);
            
            // 10. 构建响应
            long responseTime = System.currentTimeMillis() - startTime;
            
            ChatResponse response = new ChatResponse();
            response.setSessionId(session.getSessionId());
            response.setMessage(aiResponse);
            response.setAudioUrl(null); // 语音异步生成，初始为null
            response.setSkillUsed(selectedSkill);
            response.setEmotionDetected(detectedEmotion);
            response.setResponseTime(responseTime);
            response.setCharacter(convertToCharacterDTO(character));
            response.setSuccess(true);
            
            log.info("聊天完成: 角色={}, 技能={}, 情感={}, 响应时间={}ms", 
                    character.getName(), selectedSkill, detectedEmotion, responseTime);
            
            return response;
            
        } catch (Exception e) {
            log.error("聊天处理失败", e);
            return new ChatResponse("抱歉，处理您的消息时出现了错误，请稍后再试。");
        }
    }
    
    @Transactional
    private ChatSession getOrCreateSessionTransactional(ChatRequest request, Character character) {
        // 获取当前认证用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        Optional<User> userOpt = userService.findByUsername(username);
        
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        
        // 1. 如果提供了sessionId，尝试恢复该会话
        if (request.getSessionId() != null) {
            Optional<ChatSession> existingSession = sessionRepository.findBySessionId(request.getSessionId());
            if (existingSession.isPresent()) {
                ChatSession session = existingSession.get();
                // 验证会话属于当前用户
                if (session.getUser() != null && session.getUser().getId().equals(user.getId())) {
                    return session;
                }
            }
        }
        
        // 2. 如果请求明确要求新对话，创建新会话
        if (request.isNewConversation()) {
            return createNewSession(user, character);
        }
        
        // 3. 自动查找用户与该角色的最新活跃会话
        Optional<ChatSession> latestSession = sessionRepository.findFirstByUserAndCharacterAndIsActiveTrueOrderByUpdatedAtDesc(user, character);
        if (latestSession.isPresent()) {
            log.info("自动恢复用户 {} 与角色 {} 的对话会话: {}", username, character.getName(), latestSession.get().getSessionId());
            return latestSession.get();
        }
        
        // 4. 如果没有找到现有会话，创建新会话
        return createNewSession(user, character);
    }
    
    private ChatSession createNewSession(User user, Character character) {
        ChatSession session = new ChatSession();
        session.setSessionId(UUID.randomUUID().toString());
        session.setCharacter(character);
        session.setUser(user);
        session.setSessionTitle("与" + character.getName() + "的对话");
        
        log.info("为用户 {} 与角色 {} 创建新对话会话: {}", user.getUsername(), character.getName(), session.getSessionId());
        return sessionRepository.save(session);
    }
    
    @Transactional
    private ChatMessage saveUserMessageTransactional(ChatSession session, ChatRequest request) {
        ChatMessage message = new ChatMessage();
        message.setSession(session);
        message.setMessageType(ChatMessage.MessageType.USER);
        message.setContent(request.getMessage());
        message.setAudioUrl(request.getAudioUrl());
        
        return messageRepository.save(message);
    }
    
    private String generateAIResponse(Character character, String userMessage, String skill, ChatSession session) {
        try {
            String basePrompt = character.getSystemPrompt();
            String enhancedPrompt = enhancePromptWithSkill(basePrompt, userMessage, skill, character, session);
            
            log.info("开始生成AI回复 - 角色: {}, 用户消息: {}, 技能: {}", 
                    character.getName(), userMessage, skill);
            
            String response = llmService.generateResponse(enhancedPrompt, userMessage, character.getName())
                    .block(); // 使用block()等待响应，在生产环境中应该使用异步处理
            
            log.info("AI回复生成成功 - 角色: {}, 回复长度: {}", 
                    character.getName(), response != null ? response.length() : 0);
            
            return response;
                    
        } catch (Exception e) {
            log.error("生成AI回复失败 - 角色: {}, 用户消息: {}", character.getName(), userMessage, e);
            return "抱歉，我现在有点困惑，能再说一遍吗？";
        }
    }
    
    /**
     * 异步生成AI回复（优化版本）
     */
    private String generateAIResponseAsync(Character character, String userMessage, String skill, ChatSession session) {
        try {
            // 检查缓存中是否有常见问题的快速回复
            String cacheKey = character.getId() + "_" + userMessage.toLowerCase().trim();
            String cachedResponse = responseCache.get(cacheKey);
            if (cachedResponse != null) {
                log.info("使用缓存回复 - 角色: {}, 用户消息: {}", character.getName(), userMessage);
                return cachedResponse;
            }
            
            String basePrompt = character.getSystemPrompt();
            String enhancedPrompt = enhancePromptWithSkill(basePrompt, userMessage, skill, character, session);
            
            log.info("开始生成AI回复 - 角色: {}, 用户消息: {}, 技能: {}", 
                    character.getName(), userMessage, skill);
            
            // 使用更短的超时时间，避免长时间等待
            String response = llmService.generateResponse(enhancedPrompt, userMessage, character.getName())
                    .timeout(java.time.Duration.ofSeconds(15)) // 15秒超时
                    .block();
            
            // 缓存常见问题的回复（只缓存短回复）
            if (response != null && response.length() < 100) {
                responseCache.put(cacheKey, response);
                // 限制缓存大小，避免内存泄漏
                if (responseCache.size() > 1000) {
                    responseCache.clear();
                }
            }
            
            log.info("AI回复生成成功 - 角色: {}, 回复长度: {}", 
                    character.getName(), response != null ? response.length() : 0);
            
            return response;
                    
        } catch (Exception e) {
            log.error("生成AI回复失败 - 角色: {}, 用户消息: {}", character.getName(), userMessage, e);
            return "抱歉，我现在有点困惑，能再说一遍吗？";
        }
    }
    
    /**
     * 异步生成语音
     */
    private void generateAudioAsync(String text, String characterName, ChatMessage message) {
        // 使用异步方式生成语音，不阻塞主流程
        voiceService.textToSpeech(text, characterName)
                .subscribe(
                    audioUrl -> {
                        // 更新消息的音频URL
                        message.setAudioUrl(audioUrl);
                        messageRepository.save(message);
                        log.info("语音生成完成: {}", audioUrl);
                    },
                    error -> {
                        log.error("语音生成失败", error);
                        // 语音生成失败不影响主流程
                    }
                );
    }
    
    private String enhancePromptWithSkill(String basePrompt, String userMessage, String skill, 
                                        Character character, ChatSession session) {
        switch (skill) {
            case "knowledge":
                return aiSkillService.enhanceKnowledgeResponse(basePrompt, userMessage, character.getKnowledgeBase());
            
            case "emotion":
                String emotion = aiSkillService.detectEmotion(userMessage);
                return aiSkillService.enhanceEmotionalResponse(basePrompt, userMessage, emotion);
            
            case "creative":
                return aiSkillService.enhanceCreativeResponse(basePrompt, userMessage);
            
            case "memory":
                List<String> recentMessages = getRecentMessages(session);
                return aiSkillService.enhanceMemoryResponse(basePrompt, recentMessages);
            
            case "analyze":
                return aiSkillService.enhanceAnalysisResponse(basePrompt, userMessage);
            
            default:
                return basePrompt;
        }
    }
    
    private List<String> getRecentMessages(ChatSession session) {
        return messageRepository.findBySessionSessionIdOrderByCreatedAtAsc(session.getSessionId())
                .stream()
                .map(ChatMessage::getContent)
                .collect(Collectors.toList());
    }
    
    private ChatMessage saveAIMessage(ChatSession session, String content, String skill, String emotion) {
        ChatMessage message = new ChatMessage();
        message.setSession(session);
        message.setMessageType(ChatMessage.MessageType.ASSISTANT);
        message.setContent(content);
        message.setSkillUsed(skill);
        message.setEmotionDetected(emotion);
        
        return messageRepository.save(message);
    }
    
    @Transactional
    private ChatMessage saveAIResponseTransactional(ChatSession session, String content, String skill, String emotion, Long characterId) {
        // 保存AI消息（不包含语音生成）
        ChatMessage message = new ChatMessage();
        message.setSession(session);
        message.setMessageType(ChatMessage.MessageType.ASSISTANT);
        message.setContent(content);
        message.setSkillUsed(skill);
        message.setEmotionDetected(emotion);
        // 语音URL将在异步生成后更新
        
        ChatMessage savedMessage = messageRepository.save(message);
        
        // 更新会话统计
        session.setMessageCount(session.getMessageCount() + 2); // 用户消息 + AI回复
        sessionRepository.save(session);
        
        // 更新角色聊天次数统计
        characterService.incrementChatCount(characterId);
        
        return savedMessage;
    }
    
    private void updateSessionStats(ChatSession session) {
        session.setMessageCount(session.getMessageCount() + 2); // 用户消息 + AI回复
        sessionRepository.save(session);
    }
    
    private CharacterDTO convertToCharacterDTO(Character character) {
        CharacterDTO dto = new CharacterDTO();
        dto.setId(character.getId());
        dto.setName(character.getName());
        dto.setDescription(character.getDescription());
        dto.setAvatarUrl(character.getAvatarUrl());
        dto.setCategory(character.getCategory());
        dto.setChatCount(character.getChatCount());
        return dto;
    }
    
    public List<ChatMessageDTO> getChatHistory(String sessionId) {
        List<ChatMessage> messages = messageRepository.findBySessionSessionIdOrderByCreatedAtAsc(sessionId);
        return messages.stream()
                .map(ChatMessageDTO::new)
                .collect(Collectors.toList());
    }
    
    public ChatSessionDTO getSessionInfo(String sessionId) {
        Optional<ChatSession> sessionOpt = sessionRepository.findBySessionId(sessionId);
        if (sessionOpt.isPresent()) {
            return new ChatSessionDTO(sessionOpt.get());
        }
        return null;
    }
    
    public List<ChatSession> getUserSessions(String userId) {
        // 如果传入的是用户ID（数字），则查找已登录用户的会话
        try {
            Long userIdLong = Long.parseLong(userId);
            Optional<User> userOpt = userService.findById(userIdLong);
            if (userOpt.isPresent()) {
                return sessionRepository.findByUserAndIsActiveTrueOrderByUpdatedAtDesc(userOpt.get());
            }
        } catch (NumberFormatException e) {
            // 如果不是数字，则查找匿名用户的会话
            return sessionRepository.findByAnonymousUserIdAndIsActiveTrueOrderByUpdatedAtDesc(userId);
        }
        return List.of();
    }
    
    public List<ChatSessionDTO> getCurrentUserSessions() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.isAuthenticated() && !"anonymousUser".equals(authentication.getName())) {
            // 已登录用户
            String username = authentication.getName();
            Optional<User> userOpt = userService.findByUsername(username);
            if (userOpt.isPresent()) {
                List<ChatSession> sessions = sessionRepository.findByUserAndIsActiveTrueOrderByUpdatedAtDesc(userOpt.get());
                return sessions.stream()
                        .map(ChatSessionDTO::new)
                        .collect(java.util.stream.Collectors.toList());
            }
        }
        return List.of(); // 匿名用户返回空列表
    }
    
    /**
     * 获取用户与特定角色的对话历史（最新会话）
     */
    public List<ChatMessageDTO> getCharacterConversation(Long characterId) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated() || "anonymousUser".equals(authentication.getName())) {
            throw new RuntimeException("请先登录");
        }
        
        String username = authentication.getName();
        Optional<User> userOpt = userService.findByUsername(username);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        Optional<Character> characterOpt = characterService.findById(characterId);
        if (!characterOpt.isPresent()) {
            throw new RuntimeException("角色不存在");
        }
        
        Character character = characterOpt.get();
        Optional<ChatSession> latestSession = sessionRepository.findFirstByUserAndCharacterAndIsActiveTrueOrderByUpdatedAtDesc(user, character);
        
        if (latestSession.isPresent()) {
            return getChatHistory(latestSession.get().getSessionId());
        } else {
            return List.of(); // 返回空列表
        }
    }
    
    /**
     * 开始与角色的新对话
     */
    public ChatSessionDTO startNewConversation(Long characterId) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated() || "anonymousUser".equals(authentication.getName())) {
            throw new RuntimeException("请先登录");
        }
        
        String username = authentication.getName();
        Optional<User> userOpt = userService.findByUsername(username);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        Optional<Character> characterOpt = characterService.findById(characterId);
        if (!characterOpt.isPresent()) {
            throw new RuntimeException("角色不存在");
        }
        
        Character character = characterOpt.get();
        ChatSession newSession = createNewSession(user, character);
        return new ChatSessionDTO(newSession);
    }
    
    /**
     * 获取用户与特定角色的所有会话
     */
    public List<ChatSessionDTO> getCharacterSessions(Long characterId) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated() || "anonymousUser".equals(authentication.getName())) {
            throw new RuntimeException("请先登录");
        }
        
        String username = authentication.getName();
        Optional<User> userOpt = userService.findByUsername(username);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        Optional<Character> characterOpt = characterService.findById(characterId);
        if (!characterOpt.isPresent()) {
            throw new RuntimeException("角色不存在");
        }
        
        Character character = characterOpt.get();
        List<ChatSession> sessions = sessionRepository.findByUserAndCharacterAndIsActiveTrueOrderByUpdatedAtDesc(user, character);
        
        return sessions.stream()
                .map(ChatSessionDTO::new)
                .collect(Collectors.toList());
    }
    
    /**
     * 删除聊天会话
     */
    public boolean deleteSession(String sessionId) {
        try {
            log.info("删除聊天会话: {}", sessionId);
            
            // 查找会话
            Optional<ChatSession> sessionOpt = sessionRepository.findBySessionId(sessionId);
            if (sessionOpt.isEmpty()) {
                log.warn("会话不存在: {}", sessionId);
                return false;
            }
            
            ChatSession session = sessionOpt.get();
            
            // 检查权限（只有会话所有者可以删除）
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.isAuthenticated() && 
                !(authentication instanceof AnonymousAuthenticationToken)) {
                
                String username = authentication.getName();
                Optional<User> userOpt = userService.findByUsername(username);
                
                if (userOpt.isPresent() && session.getUser() != null && 
                    session.getUser().getUsername().equals(username)) {
                    
                    // 删除会话（软删除）
                    session.setIsActive(false);
                    sessionRepository.save(session);
                    
                    log.info("会话删除成功: {}", sessionId);
                    return true;
                } else {
                    log.warn("用户 {} 无权限删除会话 {}", username, sessionId);
                    return false;
                }
            } else {
                // 匿名用户不能删除会话
                log.warn("匿名用户不能删除会话: {}", sessionId);
                return false;
            }
            
        } catch (Exception e) {
            log.error("删除会话失败: {}", sessionId, e);
            return false;
        }
    }
    
    /**
     * 获取消息的语音状态
     */
    public Map<String, Object> getAudioStatus(Long messageId) {
        try {
            Optional<ChatMessage> messageOpt = messageRepository.findById(messageId);
            if (messageOpt.isEmpty()) {
                return Map.of("error", "消息不存在");
            }
            
            ChatMessage message = messageOpt.get();
            Map<String, Object> status = new HashMap<>();
            status.put("messageId", messageId);
            status.put("hasAudio", message.getAudioUrl() != null && !message.getAudioUrl().trim().isEmpty());
            status.put("audioUrl", message.getAudioUrl());
            
            return status;
        } catch (Exception e) {
            log.error("获取语音状态失败: {}", messageId, e);
            return Map.of("error", "获取语音状态失败");
        }
    }
} 